package aio;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CountDownLatch;

/**
 * Created by GanJc on 2015/11/16.
 */
public class TimeClient {

    private static final Logger logger = LoggerFactory.getLogger(TimeClient.class);

    public static void main(String[] args) {
        int port = 8888 ;
        new Thread(new AsyncTimeClientHandler("127.0.0.1",port),"aio-time-client").start();
    }

    private static class AsyncTimeClientHandler implements Runnable,CompletionHandler<Void,AsyncTimeClientHandler>{

        private String host ;

        private int port ;

        private CountDownLatch countDownLatch ;

        private AsynchronousSocketChannel client ;

        public AsyncTimeClientHandler(String host, int port) {
            this.host = host;
            this.port = port;
            this.countDownLatch = new CountDownLatch(1);
            try {
                this.client = AsynchronousSocketChannel.open();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            client.connect(new InetSocketAddress(host, port), this, this);
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void completed(Void result, AsyncTimeClientHandler attachment) {
            byte[] req = "TIME".getBytes();
            final ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
            writeBuffer.put(req).flip();
            client.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {
                @Override
                public void completed(Integer result, ByteBuffer attachment) {
                    if(attachment.hasRemaining()){
                        client.write(attachment,attachment,this);
                    }else {
                        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                        client.read(readBuffer, readBuffer, new CompletionHandler<Integer, ByteBuffer>() {
                            @Override
                            public void completed(Integer result, ByteBuffer attachment) {
                                attachment.flip();
                                byte[] bytes = new byte[attachment.remaining()];
                                attachment.get(bytes);
                                try {
                                    String body = new String(bytes,"utf-8");
                                    logger.info("aio客户端收到回复：{}" ,body);
                                    countDownLatch.countDown();
                                } catch (UnsupportedEncodingException e) {
                                    e.printStackTrace();
                                }
                            }

                            @Override
                            public void failed(Throwable exc, ByteBuffer attachment) {
                                try {
                                    client.close();
                                    countDownLatch.countDown();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }
                }

                @Override
                public void failed(Throwable exc, ByteBuffer attachment) {
                    try {
                        client.close();
                        countDownLatch.countDown();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        @Override
        public void failed(Throwable exc, AsyncTimeClientHandler attachment) {
            try {
                client.close();
                countDownLatch.countDown();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
